import re
from datetime import datetime

months_as_text = 'jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec|january|february|march|april|june|july|august|september|october|november|december'

months_as_regex = '(?:\d{1,2}|%s)' % months_as_text
months_as_datetime = ['%m', '%b', '%B']

days_as_regex = '(?:\d{1,2}(?:st|nd|rd|rth|th){0,1})'
days_as_datetime = ['%d']

years_as_regex = '(?:(?:\d{2}){1,2})'
years_as_datetime = ['%y', '%Y']

regex_dict = dict(day=days_as_regex, month=months_as_regex, year=years_as_regex)

def make_format(s):
    compiled = s % regex_dict
    regex = re.compile(s % regex_dict)
    datetime_formats = []

    for month in months_as_datetime:
        for day in days_as_datetime:
            for year in years_as_datetime:
                data = dict(month=month, day=day, year=year)
                datetime_formats.append(s % data)

    return regex, datetime_formats

date_formats = [
    make_format('%(day)s/%(month)s/%(year)s'),
    make_format('%(month)s/%(day)s/%(year)s'),
    make_format('%(year)s-%(month)s-%(day)s'),
    make_format('%(month)s-%(day)s-%(year)s'),
    make_format('%(day)s-%(month)s-%(year)s'),
    make_format('%(day)s %(month)s %(year)s'),
    make_format('%(month)s %(day)s %(year)s'),
    make_format('%(day)s %(month)s, %(year)s'),
    make_format('%(month)s %(day)s, %(year)s'),
    make_format('%(day)s %(month)s , %(year)s'),
    make_format('%(month)s %(day)s , %(year)s'),
    make_format('%(day)s, %(month)s, %(year)s'),
    ]

# Need to replace stuff like 1st and 31st with 1. This is
# faster than making a ton more datetime tries.
replacements = [('1st', '1'), ('2nd', '2'), ('3rd', '3')]
replacements += [('%dth' % x, '%d' % x) for x in range(4, 32)]

def find_dates(text):
    """
    Looks through text, returning strings of text that seems to be dates.
    """
    matches = set()
    for reg_exp, formats in date_formats:
        results = reg_exp.findall(text)
        matches.update(results)

    return list(matches)

def convert_dates(dates):
    """
    Takes a list of strings that should be some sort of date and tries to
    convert them into a list of datetime objects.
    """
    results = set()

    for date in dates:
        for replacement in replacements:
            text_from, text_to = replacement
            date = date.replace(text_from, text_to)

        for reg_exp, formats in date_formats:
            if reg_exp.search(date) != None:
                for format in formats:
                    try:
                        result = datetime.strptime(date, format)
                        results.add(result)
                    except ValueError:
                        pass

    return list(results)
